package general.datastructures;

/**
 * Simple Datastructure for storing two float values as a 2-dimensional-vector
 *
 */

public class Vector2f {
	
	private float x;
	private float y;
	
	public Vector2f(float x, float y)
	{
		this.x = x;
		this.y = y;
	}
	
	public Vector2f(float xy)
	{
		this.x = xy;
		this.y = xy;
	}
	
	public Vector2f(Vector2f vec)
	{
		this.x = vec.x;
		this.y = vec.y;
	}
	
	public synchronized float x()
	{
		return this.x;
	}
	
	public synchronized float y()
	{
		return this.y;
	}
	
	/**
	 * Inverts the {@link Vector2f} by negating its values
	 */
	public synchronized void invert()
	{
		this.x = -this.x;
		this.y = -this.y;
	}
	
	/**
	 * Adds two {@link Vector2f} by adding their x- / y-values
	 * @param vec
	 */
	public synchronized void add(Vector2f vec)
	{
		this.x += vec.x;
		this.y += vec.y;
	}
	
	public synchronized Vector2f add_cpy(Vector2f vec)
	{
		return new Vector2f(this.x+vec.x, this.y+vec.y);
	}
	
	/**
	 * Shortens the {@link Vector2f} to the normal value 1
	 */
	public synchronized void normalize()
	{
		float length = this.length();
		this.x /= length;
		this.y /= length;
	}
	
	public synchronized void round()
	{
		this.x = Math.round(x);
		this.y = Math.round(y);
	}

	public synchronized Vector2f round_cpy()
	{
		return new Vector2f(Math.round(x),Math.round(y));
	}
	
	
	/**
	 * Rotates a {@link Vector2f} 
	 * @param angle The angle the {@link Vector2f} will be rotated to
	 */
	public synchronized void rotate(float angle)
	{
		float x = this.x;
		float y = this.y;
		this.x =(float)((Math.cos(angle)*x) + (Math.sin(angle)*y));
		this.y =(float)(-(Math.sin(angle)*x) + (Math.cos(angle)*y));
	}
	
	public synchronized Vector2f rotate_cpy(float angle)  
	{
		return new Vector2f(0);
	}
	
	/**
	 * Scales a {@link Vector2f} by a specific amount
	 * @param scale Scalingcoefficient
	 */
	public synchronized void scale(float scale)
	{
		this.x *= scale;
		this.y *= scale;
	}
	
	/**
	 * Creates a copy of a {@link Vector2f} which is scaled by the scale
	 * @param scale Scalingcoefficient
	 * @return Scaled copy of a {@link Vector2f}
	 */
	public synchronized Vector2f scale_cpy(float scale)
	{
		return new Vector2f(this.x * scale, this.y * scale);
	}
	
	/**
	 * Calculates the length of a {@link Vector2f} by using theorem of Pythagoras
	 * @return Length of a {@link Vector2f}
	 */
	public synchronized float length()
	{
		return (float) Math.sqrt(x * x + y * y);
	}
	
	public synchronized float getDistanceTo(Vector2f vec)
	{
		return subtract(this,vec).length();
	}
	
	/**
	 * Checks if a {@link Vector2f} is long enough for a specific range
	 * @param vec Vector which should be checked
	 * @param range Range in which the Vectorlength has to be
	 * @return Is in range or not
	 */
	public synchronized boolean isInRange(Vector2f vec, float range)
	{
		return (getDistanceTo(vec)<range);
	}
	
	/**
	 * Prints the {@link Vector2f} as a string in form: (x|y)
	 */
	@Override
	public synchronized String toString()
	{
		return "("+x+"|"+y+")";
	}	
	
	@Override
	public synchronized boolean equals(Object obj) {
		return (this.x == ((Vector2f)obj).x && this.y == ((Vector2f)obj).y);
	}
	
	/**
	 * Adds two {@link Vector2f}
	 * @param vec1 First {@link Vector2f} to add
	 * @param vec2 Second {@link Vector2f} to add
	 * @return
	 */
	public static Vector2f add(Vector2f vec1, Vector2f vec2)
	{
		return new Vector2f(vec1.x + vec2.x, vec1.y + vec2.y);
	}
	
	/**
	 * Substract two {@link Vector2f}
	 * @param vec1 First {@link Vector2f} which will be substracted from
	 * @param vec2 Second {@link Vector2f} which substracts
	 * @return
	 */
	public static Vector2f subtract(Vector2f vec1, Vector2f vec2)
	{
		return new Vector2f(vec1.x - vec2.x, vec1.y - vec2.y);
	}
	
}
